package com.huaxin.device.service;

import com.huaxin.hxenum.enums.ComparisonOperator;
import com.huaxin.hxenum.enums.DataType;

import java.math.BigDecimal;
import java.util.StringTokenizer;

/*
 * 表达式计算工具类
 */
public class DeviceAlarmEvaluator {

    /**
     * 计算当前值是否满足阈值条件
     */
    public static boolean isValueExceeded(DataType dataType, Object currentValue, String thresholdValueStr, ComparisonOperator comparisonOperator) {
        if (currentValue == null || thresholdValueStr == null || comparisonOperator == null) {
            return false;
        }

        // 转换 currentValue 为字符串便于后续处理
        String currentValueStr = currentValue.toString().trim();
        thresholdValueStr = thresholdValueStr.trim();

        // 判断是否为 RANGE / OUTSIDE_RANGE 类型（仅适用于数值）
        if (ComparisonOperator.RANGE.equals(comparisonOperator)) {
            return evaluateInRange(parseDecimal(currentValueStr), thresholdValueStr);
        }
        if (ComparisonOperator.OUTSIDE_RANGE.equals(comparisonOperator)) {
            return evaluateOutsideRange(parseDecimal(currentValueStr), thresholdValueStr);
        }

        if (dataType == null) {
            dataType = inferType(currentValueStr, thresholdValueStr);
        }

        return switch (dataType) {
            case NUMBER -> {
                BigDecimal current = parseDecimal(currentValueStr);
                BigDecimal threshold = parseDecimal(thresholdValueStr);
                if (current == null || threshold == null) yield false;
                yield compare(current, threshold, comparisonOperator);
            }
            case BOOLEAN -> {
                Boolean current = parseBoolean(currentValueStr);
                Boolean threshold = parseBoolean(thresholdValueStr);
                if (current == null || threshold == null) yield false;
                yield compareBoolean(current, threshold, comparisonOperator);
            }
            case STRING -> {
                // 视为字符串枚举比较（例如 BreakerStatus）
                yield compareString(currentValueStr, thresholdValueStr, comparisonOperator);
            }
            default -> false;
        };
    }

    /**
     * 推断值的类型：优先级为 Boolean > Number > String
     */
    private static DataType inferType(String val1, String val2) {
        String combined = (val1 + "," + val2).toLowerCase();
        if (combined.equals("true") || combined.equals("false") ||
                combined.contains("true") && combined.contains("false")) {
            return DataType.BOOLEAN;
        }
        try {
            parseDecimal(val1);
            parseDecimal(val2);
            return DataType.NUMBER;
        } catch (Exception ignored) {
        }
        return DataType.STRING; // 默认视为字符串枚举
    }

    /**
     * 基础数值比较：>, >=, <, <=, =, !=
     */
    private static boolean compare(BigDecimal left, BigDecimal right, ComparisonOperator op) {
        return switch (op) {
            case GREATER_THAN -> left.compareTo(right) > 0;
            case GREATER_THAN_OR_EQUAL -> left.compareTo(right) >= 0;
            case LESS_THAN -> left.compareTo(right) < 0;
            case LESS_THAN_OR_EQUAL -> left.compareTo(right) <= 0;
            case EQUAL -> left.compareTo(right) == 0;
            case NOT_EQUAL -> left.compareTo(right) != 0;
            default -> false;
        };
    }

    /**
     * 布尔比较：只支持 EQUAL 和 NOT_EQUAL
     */
    private static boolean compareBoolean(Boolean current, Boolean threshold, ComparisonOperator op) {
        return switch (op) {
            case EQUAL -> current.equals(threshold);
            case NOT_EQUAL -> !current.equals(threshold);
            default -> false; // 其他操作无意义
        };
    }

    /**
     * 字符串比较（用于枚举等）
     */
    private static boolean compareString(String current, String threshold, ComparisonOperator op) {
        boolean isEqual = current.equalsIgnoreCase(threshold);
        return switch (op) {
            case EQUAL -> isEqual;
            case NOT_EQUAL -> !isEqual;
            default -> false;
        };
    }

    /**
     * 在范围内：min < value < max （开区间）
     */
    private static boolean evaluateInRange(BigDecimal value, String thresholdValue) {
        if (value == null) return false;
        BigDecimal[] bounds = parseMinMax(thresholdValue);
        BigDecimal min = bounds[0];
        BigDecimal max = bounds[1];
        return value.compareTo(min) > 0 && value.compareTo(max) < 0;
    }

    /**
     * 范围外：value < min OR value > max
     */
    private static boolean evaluateOutsideRange(BigDecimal value, String thresholdValue) {
        if (value == null) return false;
        BigDecimal[] bounds = parseMinMax(thresholdValue);
        BigDecimal min = bounds[0];
        BigDecimal max = bounds[1];
        return value.compareTo(min) < 0 || value.compareTo(max) > 0;
    }

    /**
     * 解析 "min,max" 字符串为 BigDecimal[2]
     */
    private static BigDecimal[] parseMinMax(String thresholdValue) {
        if (thresholdValue == null || thresholdValue.trim().isEmpty()) {
            throw new IllegalArgumentException("阈值不能为空");
        }
        StringTokenizer st = new StringTokenizer(thresholdValue.trim(), ",");
        if (st.countTokens() != 2) {
            throw new IllegalArgumentException("RANGE/OUTSIDE_RANGE 类型必须提供两个值，格式为 'min,max'，当前值: " + thresholdValue);
        }
        try {
            BigDecimal min = new BigDecimal(st.nextToken().trim());
            BigDecimal max = new BigDecimal(st.nextToken().trim());
            if (min.compareTo(max) >= 0) {
                throw new IllegalArgumentException("min 必须小于 max，当前值: " + min + "," + max);
            }
            return new BigDecimal[]{min, max};
        } catch (NumberFormatException e) {
            throw new IllegalArgumentException("阈值必须为数字，格式 'min,max'，当前值: " + thresholdValue, e);
        }
    }

    /**
     * 安全解析字符串为 BigDecimal
     */
    public static BigDecimal parseDecimal(String value) {
        if (value == null || value.trim().isEmpty()) {
            return null;
        }
        try {
            return new BigDecimal(value.trim());
        } catch (NumberFormatException e) {
            return null;
        }
    }

    /**
     * 安全解析字符串为 Boolean
     */
    public static Boolean parseBoolean(String value) {
        if (value == null) return null;
        String v = value.trim().toLowerCase();
        if ("true".equals(v)) return true;
        if ("false".equals(v)) return false;
        return null;
    }
}